<template>
  <van-form
      ref="formRef"
      :model="formData"
      @submit="onSubmit"
      class="vant-form"
  >
    <van-field
        v-for="(item, index) in columns"
        :key="index"
        :name="item.prop"
        :label="item.label"
        :placeholder="item.placeholder || `请输入${item.label}`"
        :rules="getRules(item)"
        :type="getFieldType(item.type)"
        v-model="formData[item.prop]"
        :required="item.required"
        :disabled="item.disabled"
    >
      <template v-if="item.type === 'select' && item.options" #input>
        <van-select
            v-model="formData[item.prop]"
            :placeholder="item.placeholder || `请选择${item.label}`"
        >
          <van-option
              v-for="opt in item.options"
              :key="opt.value"
              :label="opt.label"
              :value="opt.value"
          />
        </van-select>
      </template>

      <template v-if="item.type === 'date'">
        <van-date-picker
            v-model="formData[item.prop]"
            :title="item.label"
            :placeholder="item.placeholder"
            @confirm="onDateConfirm(item.prop)"
        />
      </template>
    </van-field>
  </van-form>
</template>

<script setup lang="ts">
import { defineProps, defineEmits, ref, watch } from 'vue';
import { VanForm, VanField, VanSelect, VanOption, VanDatePicker, VanFormInstance } from 'vant';

// 定义表单项目类型
type FormItemType = 'text' | 'number' | 'password' | 'select' | 'date' | 'textarea';

// 定义单个表单项的配置接口
interface FormColumn {
  prop: string;               // 字段名
  label: string;              // 标签文本
  type: FormItemType;         // 表单组件类型
  required?: boolean;         // 是否必填
  rules?: any[];              // 验证规则
  placeholder?: string;       // 占位文本
  disabled?: boolean;         // 是否禁用
  options?: { label: string; value: any }[]; // 选择类组件的选项
}

// 定义表单数据类型
type FormData = Record<string, any>;

// 入参定义
const props = defineProps<{
  columns: FormColumn[];  // 表单列配置
  formData: FormData;     // 表单数据对象
}>();

// 出参事件定义
const emit = defineEmits<{
  (e: 'set-columns', columns: FormColumn[]): void;  // 设置columns的方法
  (e: 'set-form-data', formData: FormData): void;    // 设置formData的方法
}>();

// 表单引用
const formRef = ref<VanFormInstance | null>(null);

// 获取字段类型
const getFieldType = (type: FormItemType): string => {
  switch (type) {
    case 'text':
      return 'text';
    case 'number':
      return 'number';
    case 'password':
      return 'password';
    case 'textarea':
      return 'textarea';
    default:
      return 'text';
  }
};

// 获取验证规则
const getRules = (item: FormColumn) => {
  const rules = [];

  if (item.required) {
    rules.push({
      required: true,
      message: `${item.label}不能为空`,
    });
  }

  if (item.rules && item.rules.length) {
    rules.push(...item.rules);
  }

  return rules;
};

// 日期选择确认
const onDateConfirm = (prop: string) => {
  // 可以在这里处理日期选择后的逻辑
};

// 表单提交
const onSubmit = (values: FormData) => {
  // 表单提交逻辑
};

// 设置columns
const setColumns = (columns: FormColumn[]) => {
  emit('set-columns', columns);
};

// 设置formData
const setFormData = (formData: FormData) => {
  emit('set-form-data', formData);
};

// 获取表单数据
const getFormData = (): FormData => {
  return { ...props.formData };
};

// 表单验证方法
const validate = async (): Promise<boolean> => {
  if (!formRef.value) return false;
  try {
    await formRef.value.validate();
    return true;
  } catch (error) {
    return false;
  }
};

// 验证部分字段
const validateField = async (name: string | string[]): Promise<boolean> => {
  if (!formRef.value) return false;
  try {
    await formRef.value.validate(name);
    return true;
  } catch (error) {
    return false;
  }
};

// 清除验证状态
const clearValidate = (name?: string | string[]) => {
  formRef.value?.clearValidate(name);
};

// 监听数据变化
watch(
    () => props.formData,
    () => {},
    { deep: true }
);

watch(
    () => props.columns,
    () => {},
    { deep: true }
);

// 暴露组件方法
defineExpose({
  setColumns,
  setFormData,
  getFormData,
  validate,
  validateField,
  clearValidate
});
</script>

<style scoped>
.vant-form {
  padding: 16px;
  background-color: #fff;
}

.van-field {
  margin-bottom: 16px;
}
</style>
